﻿//*****************************************************
//作者:B站@RefYoung
//作品地址:https://www.bilibili.com/video/BV1qz4y1V7gh/?spm_id_from=333.999.0.0&vd_source=74e22f06d72332d1e05dd174982593b1
//程序和代码链接：https://pan.baidu.com/s/1jadfMtsYq5quT8wQLNvKEg 
//提取码：2wci

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //加载配置文件
    loadConfig();

    this->resize(g_animationWidth,g_animationHeight);
    //设置中心组件
    this->setCentralWidget(ui->labBackImg);

    //安装事件过滤器
    this->installEventFilter(this);


    //初始化退出参数
    m_quit = false;
    m_start = false;
    m_drag = false;

    //初始化状态
    m_state = STATE::STAY;

    //默认为混合动画模式
    m_animationModel = ANIMATIONMODE::MIX;


    //初始化桌面长宽
    m_desktopWidth = QApplication::desktop()->width();
    m_desktopHeight = QApplication::desktop()->height();

    //设置阴影
    m_graphicsEffet.setColor(QColor(0,0,0,25));//设置阴影颜色和透明度
    m_graphicsEffet.setBlurRadius(5);//设置阴影模糊度
    this->setGraphicsEffect(&m_graphicsEffet);

    //设置窗口无边框和背景透明
    this->setWindowFlags(Qt::WindowType::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool);
    setAttribute(Qt::WA_TranslucentBackground);

    m_timer1 = new QTimer(this);
    m_timer2 = new QTimer(this);
    m_timer3 = new QTimer(this);
    m_timer4 = new QTimer(this);

    //设置动画速度
    m_timer1->setInterval(g_animationSpeed);
    m_timer2->setInterval(g_btnShowTime);
    m_timer3->setInterval(g_moveSpeed);

    //初始化当前帧动画为1
    m_currentFrame = 1;

    //设置action
    actChange = new QAction(QIcon(":/imgs/btnIcon/btnChange.png"),u8"切换模式",this);
    actClose = new QAction(QIcon(":/imgs/btnIcon/btnClose.png"),u8"关闭",this);


    //设置托盘图标和菜单
    QSystemTrayIcon* tray = new QSystemTrayIcon(this);
    tray->setIcon(QIcon(":/imgs/programIcon/icon.ico"));
    QMenu* menu = new QMenu(this);

    menu->addAction(actChange);
    menu->addAction(actClose);
    tray->setContextMenu(menu);
    tray->setToolTip("萝莉丝桌宠");
    tray->show();

    //设置按钮
    m_btnClose = new QPushButton(this);
    m_btnChange = new QPushButton(this);


    //设置按钮图标
    m_btnClose->setIcon(QIcon(":/imgs/btnIcon/btnClose2.png"));
    m_btnChange->setIcon(QIcon(":/imgs/btnIcon/btnChange2.png"));

    //设置按钮样式
    this->setStyleSheet("QPushButton{background-color:rgb(64,173,250);border:none;border-radius:10px}"
                        "QPushButton:hover{background-color:rgb(233,31,48)}");


    //设置按钮位置大小
    m_btnClose->setGeometry(this->width() / 2 - 50,this->height() - 32,40,30);
    m_btnChange->setGeometry(this->width() / 2 ,this->height() -  32,40,30);

    //默认隐藏按钮
    m_btnChange->hide();
    m_btnClose->hide();


    connect(m_btnChange,SIGNAL(pressed()),actChange,SLOT(trigger()));
    connect(m_btnClose,SIGNAL(pressed()),actClose,SLOT(trigger()));


    connect(actClose,SIGNAL(triggered()),this,SLOT(onBtnCloseClicked()));
    connect(actChange,SIGNAL(triggered()),this,SLOT(onBtnChangeClicked()));


    connect(m_timer1,SIGNAL(timeout()),this,SLOT(onTimer1Out()));
    connect(m_timer2,SIGNAL(timeout()),this,SLOT(onTimer2Out()));
    connect(m_timer3,SIGNAL(timeout()),this,SLOT(onTimer3Out()));
    connect(m_timer4,SIGNAL(timeout()),this,SLOT(onTimer4Out()));

    //随机载入初始动画
    QString startUp = QString(":/imgs/animation/startUp/%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(3) + 1);
    m_animationList.append(startUp);
    QString defaultAni = QString(":/imgs/animation/default/%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(3) + 1);
    m_animationList.append(defaultAni);
    m_animationIndex = 0;

    loadAnmiation();//加载动画
    m_timer4->start(5000);

}

MainWindow::~MainWindow()
{
    delete ui;
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);


    if(event->type() == QEvent::MouseButtonPress){
        if(mouseEvent->buttons() == Qt::MouseButton::LeftButton){
            m_beginPos = mouseEvent->globalPos() - this->pos();
        }else if(mouseEvent->buttons() == Qt::MouseButton::RightButton){

            m_btnChange->show();
            m_btnClose->show();
            m_timer2->start();
        }

    }else if(event->type() == QEvent::MouseMove && mouseEvent->buttons() == Qt::MouseButton::LeftButton){
        this->move(mouseEvent->globalPos() - m_beginPos);


        if(m_drag == false){
            m_drag = true;

            m_timer3->stop();
            m_animationModel = ANIMATIONMODE::KEEP;
            m_state = STATE::DRAG;
            QString ani = QString(":/imgs/animation/raise/%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(3) + 1);
            m_animationList.append(ani);
            m_animationIndex = m_animationList.count() - 1;
            loadAnmiation();

        }


    }else if(event->type() == QEvent::MouseButtonRelease ){

        m_drag = false;
        if(m_state == STATE::DRAG){
            m_state = STATE::STAY;
            m_animationList.append(":/imgs/animation/downFinish");
            m_animationIndex = m_animationList.count() - 1;

            QString defaultAni = QString(":/imgs/animation/default/%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(3) + 1);
            m_animationList.append(defaultAni);

            loadAnmiation();
        }
    }

    return false;
}

void MainWindow::loadAnmiation()
{
    QDir dir(m_animationList.at(m_animationIndex));
    if(!dir.exists() ){
        return;
    }

    QStringList imgList = dir.entryList(QDir::Filter::Files,QDir::Name);
    m_currentTotalFrame = imgList.count();
    m_currentFilePath = m_animationList.at(m_animationIndex) +"/"+imgList.at(0);
    int positon = m_currentFilePath.lastIndexOf("1");
    m_currentFilePath.remove(positon,1);
    m_currentFilePath.insert(positon,"%1");

    m_timer1->stop();
    m_currentFrame = 1;
    m_timer1->start();
}

void MainWindow::addMoveAnimation()
{
    QPoint thisPoint = this->pos();
    int thisX = thisPoint.x();
    int thisY = thisPoint.y();
    for(;;){
        int dir = QRandomGenerator(QTime::currentTime().second()).bounded(1000);
        if(dir % 4 == 0){//向左移动
            if(thisX < -m_desktopWidth / 250){
                continue;
            }
            m_moveDirection = MOVEDIRECTION::LEFT;//向左移动
            QString ani = QString(":/imgs/animation/move/left%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(2) + 1);
            m_animationList.append(ani);
            break;
        }else if(dir % 4 == 1){//向右移动
            if(thisX > m_desktopWidth - g_animationWidth){
                continue;
            }
            m_moveDirection = MOVEDIRECTION::RIGHT;//向右移动
            QString ani = QString(":/imgs/animation/move/right%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(2) + 1);
            m_animationList.append(ani);
            break;
        }else if(dir % 4 == 2){//向上移动
            if(thisY < 0){
                continue;
            }
            if(thisX < (m_desktopWidth / 2)){//左上移动
                m_moveDirection = MOVEDIRECTION::TOP;//向上移动
                m_animationList.append(":/imgs/animation/move/leftUp1");
            }else{//右上移动
                m_moveDirection = MOVEDIRECTION::TOP;//向上移动
                m_animationList.append(":/imgs/animation/move/rightUp");
            }
            break;
        }else if(dir % 4 == 3){//向下移动
            if(thisY > m_desktopHeight - g_animationHeight - 50){
                continue;
            }
            if(thisX < (m_desktopWidth / 2)){//左下移动
                m_moveDirection = MOVEDIRECTION::BOTTOM;//向左下移动
                m_animationList.append(":/imgs/animation/move/leftDown");
            }else{//右下移动
                m_moveDirection = MOVEDIRECTION::BOTTOM;//向右下移动
                m_animationList.append(":/imgs/animation/move/rightDown");
            }
            break;
        }
    }

    m_animationIndex = m_animationList.count() - 1;//平滑动画截断开关
    loadAnmiation();
}

void MainWindow::onTimer1Out()
{
        if(m_currentFrame > m_currentTotalFrame ){//重置动画
        if(m_start == false){//启动动画只执行一次
            m_start = true;

        }
            if(m_quit){
                this->close();
            }

            m_currentFrame = 1;
            if(m_animationIndex < m_animationList.count() - 1){
                ++m_animationIndex;
                if(m_animationList.count() > 100){//如果列表已经积累了100个动画则重置动画列表
                    QString temp = m_animationList.at(m_animationIndex);
                    m_animationList.clear();
                    m_animationList.append(temp);
                    m_animationIndex = m_animationList.count() - 1;
                }
            }

            loadAnmiation();
        }

        ui->labBackImg->setPixmap(QPixmap(m_currentFilePath.arg(m_currentFrame)).scaled(ui->labBackImg->width(),ui->labBackImg->height(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation));
        ++m_currentFrame;
}

void MainWindow::onTimer2Out()
{
    m_timer2->stop();
    m_btnChange->hide();
    m_btnClose->hide();
}

void MainWindow::onTimer3Out()
{
    QPoint thisPoint = this->pos();
    int thisX = thisPoint.x();
    int thisY = thisPoint.y();


    //动画设置
    if(m_state != STATE::MOVE){
            m_state = STATE::MOVE;
            addMoveAnimation();
    }


    //窗口移动
    if(m_moveDirection == MOVEDIRECTION::LEFT){//向左移动
            thisX -= g_moveDistance;
            this->move(thisX,thisY);
    }else if(m_moveDirection == MOVEDIRECTION::RIGHT){//向右移动
            thisX += g_moveDistance;
            this->move(thisX ,thisY);
    }else if(m_moveDirection == MOVEDIRECTION::TOP){//向上移动
            thisY -= g_moveDistance;
            this->move(thisX ,thisY);
    }else if(m_moveDirection == MOVEDIRECTION::BOTTOM){//向下移动
            thisY += g_moveDistance;
            this->move(thisX ,thisY);
    }

    //位置检测,防止出屏幕外
    if(m_moveDirection == MOVEDIRECTION::LEFT){//向左移动
            if(thisX < -m_desktopWidth / 250){
                addMoveAnimation();
            }
    }else if(m_moveDirection == MOVEDIRECTION::RIGHT){//向右移动
            if(thisX > m_desktopWidth - g_animationWidth){
                addMoveAnimation();
            }

    }else if(m_moveDirection == MOVEDIRECTION::TOP){//向上移动
            if(thisY < 0){
                addMoveAnimation();
            }
    }else if(m_moveDirection == MOVEDIRECTION::BOTTOM){//向下移动
            if(thisY > m_desktopHeight - g_animationHeight - 50){
                addMoveAnimation();
            }
    }

}

void MainWindow::onTimer4Out()
{
    if(m_animationModel ==ANIMATIONMODE::KEEP){//原地动画模式
            if(m_timer3->isActive()){
                m_timer3->stop();
            }

            //添加动画
            QString ret = QString(":/imgs/animation/mixAnimation/%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(25) + 1);
            m_animationList.append(ret);
            m_animationIndex = m_animationList.count() - 1;
            m_state = STATE::STAY;

    }else if(m_animationModel ==ANIMATIONMODE::SHIFT){//移动模式
            if(!m_timer3->isActive()){
                m_timer3->start();
            }

    }else if(m_animationModel ==ANIMATIONMODE::MIX){//混合模式
            int ret = QRandomGenerator(QTime::currentTime().second()).bounded(100);
            if(ret % 2){
                if(!m_timer3->isActive()){
                    m_timer3->start();
                }
                m_state = STATE::STAY;
                addMoveAnimation();
            }else{
                if(m_timer3->isActive()){
                    m_timer3->stop();
                }
                //添加动画
                QString ret = QString(":/imgs/animation/mixAnimation/%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(25) + 1);
                m_animationList.append(ret);
                m_animationIndex = m_animationList.count() - 1;
                m_state = STATE::STAY;
            }

    }

    //随机持续时间
    int interval;
    if(m_state == STAY){//原地动画,持续时间正常
       interval = QRandomGenerator(QTime::currentTime().second()).bounded(g_animationDurationMin,g_animationDurationMax);
    }else{//移动动画,持续时间较短
       interval = QRandomGenerator(QTime::currentTime().second()).bounded(3000,6000);
    }

    m_timer4->stop();

    m_timer4->start(interval);
}



void MainWindow::onBtnChangeClicked()
{
    if(m_animationModel == ANIMATIONMODE::KEEP){
       m_animationModel = ANIMATIONMODE::MIX;
       ChangeTip *c = new ChangeTip("已切换至混合模式",this);
       c->show();
       onTimer4Out();
    }else{
       m_animationModel = ANIMATIONMODE::KEEP;
       ChangeTip *c = new ChangeTip("已切换至动画模式",this);
       c->show();
       onTimer4Out();
    }
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    this->close();
    QCoreApplication::quit();
}

void MainWindow::onBtnCloseClicked()
{
    m_timer4->stop();
    m_timer3->stop();
    QString shutdown = QString(":/imgs/animation/shutdown/%1").arg(QRandomGenerator(QTime::currentTime().second()).bounded(3) + 1);
    m_animationList.append(shutdown);
    m_quit = true;
    ++m_animationIndex;
    loadAnmiation();
    onTimer2Out();
}

void MainWindow::loadConfig()
{
    g_animationWidth = animationWidth;
    g_animationHeight = animationHeight;
    g_animationSpeed = animationSpeed;
    g_btnShowTime = btnShowTime;
    g_moveSpeed = moveSpeed;
    g_moveDistance = moveDistance;
    g_animationDurationMin = animationDurationMin;
    g_animationDurationMax = animationDurationMax;


    QFile file("config.txt");
    if(file.exists()){
       file.open(QIODevice::ReadOnly | QIODevice::Text);

       QTextStream stream(&file);
       stream.setCodec("UTF-8");
       for(;!stream.atEnd();){
                QString line = stream.readLine();

                if(line.startsWith("g")){

                    QStringList datas = line.split("\t",Qt::SkipEmptyParts);

                    QString config = datas.at(0);

                    QStringList configs = config.split("=",Qt::SkipEmptyParts);

                    if(configs.at(0) == "g_animationWidth"){
                        g_animationWidth = configs.at(1).toInt();
                    }else if(configs.at(0) == "g_animationHeight"){
                        g_animationHeight = configs.at(1).toInt();
                    }else if(configs.at(0) == "g_animationSpeed"){
                        g_animationSpeed = configs.at(1).toInt();
                    }
                    else if(configs.at(0) == "g_btnShowTime"){
                        g_btnShowTime = configs.at(1).toInt();
                    }
                    else if(configs.at(0) == "g_moveSpeed"){
                        g_moveSpeed = configs.at(1).toInt();
                    }
                    else if(configs.at(0) == "g_moveDistance"){
                        g_moveDistance = configs.at(1).toInt();
                    }
                    else if(configs.at(0) == "g_animationDurationMin"){
                        g_animationDurationMin = configs.at(1).toInt();
                    }
                    else if(configs.at(0) == "g_animationDurationMax"){
                        g_animationDurationMax = configs.at(1).toInt();
                    }
                }
       }

       file.close();
    }else{

       //生成配置文件
       QFile file("config.txt");
       if(!file.exists()){
                file.open(QIODevice::WriteOnly | QIODevice::Text);
                QTextStream stream(&file);
                stream.setCodec("UTF-8");
                stream << QString("g_animationWidth=261\t//动画窗口宽度\n");
                stream << QString("g_animationHeight=249\t//动画窗口高度\n");
                stream << QString("g_animationSpeed=170\t//控制动画定时器触发时间间隔,值越大,动画越快.反之越慢\n");
                stream << QString("g_btnShowTime=5000\t//右击小萝莉时显示按钮的持续时间\n");
                stream << QString("g_moveSpeed=170\t//小萝莉自主移动的速度,值越大速度越快\n");
                stream << QString("g_moveDistance=10\t//小萝莉自主移动单步距离,值越大距离越大\n");
                stream << QString("g_animationDurationMin=10000\t//设置单个动画最小循环时间,默认最小为5s\n");
                stream << QString("g_animationDurationMax=30000\t//设置单个动画最大循环时间,默认最大为30s");
                file.close();
       }
    }
}

